Special Nodes
Problem statement
You are given an undirected tree with
tree_nodes (n)
1 ≤ n ≤ 100 000
- two integer arrays
tree_from[0 … n-2]
,tree_to[0 … n-2]
(1 ≤ tree_from[i], tree_to[i] ≤ n
)
tree_from[i]
and tree_to[i]
describe the i-th edge; the tree contains
all n
vertices and exactly n-1
edges.
A vertex v is called special if it can be an endpoint of any
diameter of the tree.
(The diameter of a tree is the longest simple path; its length is the
number of edges on that path. If several longest paths exist, we
consider the endpoints of all of them.)
Return an integer array ans[1 … n]
such that
ans[i] = 1 if vertex i is special
ans[i] = 0 otherwise
Input / output format used by the judge
The library function you must implement is
vector<int> isSpecial(int tree_nodes,
vector<int> tree_from,
vector<int> tree_to);
It has to return the binary array described above (index 0 ⇢ vertex 1).
Sample tests
Test 1
n = 3
edges = { (1,2), (2,3) }
Output : 1 0 1
Explanation: diameter is 1–2–3 so endpoints 1 and 3 are special.
Test 2
n = 7
edges =
1 2
2 3
3 4
3 5
1 6
1 7
Output : 0 0 0 1 1 1 1
Explanation:
diameters of length 4 are 4–3–2–1–6 and 4–3–2–1–7
⇒ endpoints are {4,6,7}. Node 5 is also at distance 4 from 6/7 via 3,
so {4,5,6,7} are special.
Given in Oracle OA
Approach (three linear BFS)
- Run BFS/DFS from any vertex (e.g. 0) to find a farthest vertex A.
- BFS from A to find a farthest vertex B and record
distA[ ]
; the diameter length isD = distA[B]
. - BFS from B to obtain
distB[ ]
. - A vertex
v
is an endpoint of some diameter iff
distA[v] == D OR distB[v] == D // logical OR
Every diameter has one endpoint at distance D
from A
and the other
at distance D
from B
; no other vertex satisfies this property.
Complexities
- Time
O(n)
- MemoryO(n)
Exact solution (C++17)
#include <bits/stdc++.h>
using namespace std;
/* ----------------------------------------------------------- */
/* single BFS: returns (farthest vertex, full distance vector) */
static pair<int,vector<int>>
bfs_far(int src, const vector<vector<int>>& g)
{
int n = g.size();
vector<int> dist(n, -1);
queue<int> q;
dist[src] = 0; // start
q.push(src);
int far = src;
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v : g[u])
if (dist[v] == -1) { // undiscovered
dist[v] = dist[u] + 1;
q.push(v);
if (dist[v] > dist[far]) // update only on larger distance
far = v;
}
}
return {far, dist};
}
/* ----------------------------------------------------------- */
vector<int> isSpecial(int tree_nodes,
vector<int> tree_from,
vector<int> tree_to)
{
const int n = tree_nodes;
vector<vector<int>> g(n); // adjacency list (0-based)
for (int i = 0; i < n-1; ++i) {
int a = tree_from[i] - 1;
int b = tree_to[i] - 1;
g[a].push_back(b);
g[b].push_back(a);
}
/* 1️⃣ arbitrary start → farthest vertex A */
auto [A, _] = bfs_far(0, g);
/* 2️⃣ A → farthest vertex B, get distA and diameter length D */
auto [B, distA] = bfs_far(A, g);
int D = distA[B];
/* 3️⃣ B → distB */
auto [__, distB] = bfs_far(B, g);
(void)__; // silence unused warning
/* 4️⃣ mark special nodes */
vector<int> ans(n, 0);
for (int v = 0; v < n; ++v)
if (distA[v] == D || distB[v] == D)
ans[v] = 1;
return ans; // 0 / 1 array
}
This code meets the constraints (n ≤ 10^5
) and prints exactly the
expected arrays for all the tests above.